package com.shanhy.example.agent;

import net.bytebuddy.asm.Advice;

import java.lang.reflect.Method;

/**
 * 监听拦截static方法。
 * ByteBuddy的MethodDelegation不能直接应用于静态方法。但可以使用ByteBuddy的Advice API来拦截静态方法。
 *
 * @author 单红宇
 * @date 2024-03-07 15:25:50
 */
public class MonitorStaticMethod {

    @Advice.OnMethodEnter
    public static void beforeStatic(@Advice.Local("startTime") long startTime, @Advice.Origin Method method, @Advice.AllArguments Object[] args) {
        // 在方法执行前的处理逻辑
        System.out.print("beforeStatic >>> " + method.getName() + ", args = ");
        System.out.println(args != null && args.length > 0 ? args[0] : null);
        startTime = System.currentTimeMillis();
    }

    /**
     * static方法执行结束
     * 注意：在使用@Advice.Return时，需要准确区分void方法或者有返回值的方法，
     * void方法不能包含@Advice.Return参数，并且对应的返回值类型要和方法返回值类型对应
     *
     * @param method    method
     * @param result    result
     * @param throwable throwable
     */
    @Advice.OnMethodExit(onThrowable = Throwable.class)
    public static void afterStatic(@Advice.Local("startTime") long startTime,
                                   @Advice.Origin Method method,
                                   @Advice.Return(readOnly = false) String result,
                                   @Advice.Thrown Throwable throwable) {
        // 在方法执行后的处理逻辑
        System.out.println("afterStatic >>> " + method.getName() + ", result = " + result);

        // 想要修改返回值，需要设定readOnly = false
        result = "[New] " + result;
        System.out.println("返回值被修改为：" + result);
        System.out.println("方法执行耗时：" + (System.currentTimeMillis() - startTime));
    }

}
